#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>

int main()
{
    int listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(listen_sock < 0)
    {
        perror("socket");
        return 0;
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(20001);
    addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    int ret = bind(listen_sock, (struct sockaddr*)&addr, sizeof(addr));
    if(ret < 0)
    {
        perror("bind");
        return 0;
    }

    ret = listen(listen_sock, 5); //5是已连接完成队列的大小
    if(ret < 0)
    {
        perror("listen");
        return 0;
    }

    fd_set readfds;
    FD_ZERO(&readfds);

    FD_SET(0, &readfds);
    FD_SET(listen_sock, &readfds);

    while(1)
    {
        //每次监控的时候，将readfds重新告诉select
        fd_set tmp = readfds; //给一个临时变量，每次监控的时候，只监控这个临时变量tmp
        //当select返回tmp的时候，我又把readfds给了tmp
        //这样的话 每次都能拿到想要监控的文件描述符
        
        int ret = select(listen_sock + 1, &tmp, NULL, NULL, NULL);
        if(ret < 0)
        {
            perror("select");
            return 0;
        }
        else if(ret == 0)
        {
            printf("select timeout\n");
            continue;
        }

        if(FD_ISSET(0, &tmp))
        {
            printf("0 is in tmp\n");
            char buf[1024] = {0};
            read(0, buf, sizeof(buf) - 1);
            printf("buf is : %s\n", buf);
        }
        else 
        {
            printf("0 is not tmp\n");
        }

        if(FD_ISSET(listen_sock, &tmp))
        {
            printf("listen_sock is in tmp\n");
            accept(listen_sock, NULL, NULL);
        }
        else 
        {
            printf("listen_sock is not in tmp\n");
        }
    }
    return 0;
}
